package com.yipao.wx.web.operate;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.hutool.core.util.NumberUtil;
import com.alibaba.fastjson.JSONObject;
import com.yipao.core.constant.GlobalConstant;
import com.yipao.core.util.JacksonUtil;
import com.yipao.core.util.ResponseUtil;
import com.yipao.db.domain.YipaoAdmin;
import com.yipao.db.service.YipaoAdminService;
import com.yipao.db.service.PermissionService;
import com.yipao.wx.annotation.LoginUser;
import com.yipao.wx.dto.MobileUserInfo;
import com.yipao.wx.dto.UserInfo;
import com.yipao.wx.dto.WxLoginInfo;
import com.yipao.wx.service.UserTokenManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 微信运维端权限
 *
 * @author tianhao
 * @date 2020/5/13 20:12
 **/
@RestController
@RequestMapping("/wx/auth/operate")
@Slf4j
@Validated
public class WxAuthOperateController {

    @Resource
    private WxMaService wxMaOperateService;
    @Resource
    private YipaoAdminService adminService;
    @Resource
    private PermissionService permissionService;
    @Resource
    private RedisTemplate<String, String> redisTemplate;

    /**
     * 微信登录
     *
     * @param wxLoginInfo 请求内容，{ code: xxx, userInfo: xxx }
     * @return 登录结果
     */
    @PostMapping("login")
    public Object loginByWeiXin(@RequestBody WxLoginInfo wxLoginInfo) {
        String code = wxLoginInfo.getCode();
        UserInfo userInfo2 = wxLoginInfo.getUserInfo();
        if (code == null || userInfo2 == null) {
            return ResponseUtil.badArgument();
        }

        MobileUserInfo userInfo = new MobileUserInfo();
        BeanUtils.copyProperties(wxLoginInfo, userInfo2);
        try {
            WxMaJscode2SessionResult result = this.wxMaOperateService.getUserService().getSessionInfo(code);
            userInfo.setOpenId(result.getOpenid());
            userInfo.setSessionKey(result.getSessionKey());
            userInfo.setMobile("");
        } catch (Exception e) {
            log.error("loginByWeixin exception", e);
            return ResponseUtil.fail();
        }

        YipaoAdmin admin = adminService.queryByWeixinOpenId(userInfo.getOpenId());
        if (admin == null) {
            // 无操作权限,需要绑定手机号码
            // 生成一个虚拟的用户id,负数避免重复
            Integer userId = -(NumberUtil.generateRandomNumber(100000, 999999, 1)[0]);
            userInfo.setUserId(userId);

            admin = new YipaoAdmin();
            admin.setId(userInfo.getUserId());
        } else {
            userInfo.setUserId(admin.getId());
            userInfo.setMobile(admin.getMobile());
        }

        // 将sessionKey和openId存储到redis,过期时间10分钟,避免再次获取
        redisTemplate.opsForValue().set(GlobalConstant.RedisKeyConstant.OPERATE_NOT_BIND_USER_PREFIX + userInfo.getUserId(), JSONObject.toJSONString(userInfo), 10, TimeUnit.MINUTES);

        // token
        String token = UserTokenManager.generateToken(admin.getId());

        Map<Object, Object> result = new HashMap<Object, Object>(2);
        result.put("token", token);
        result.put("userInfo", userInfo);
        return ResponseUtil.ok(result);
    }

    /**
     * 微信手机号码绑定
     *
     * @param body
     * @return
     */
    @PostMapping("bindPhone")
    public Object bindPhone(@RequestBody Map<String,String> body) {
        String userId = body.get("userId");
        String encryptedData = body.get("encryptedData");
        String iv = body.get("iv");
        String userObject = redisTemplate.opsForValue().get(GlobalConstant.RedisKeyConstant.OPERATE_NOT_BIND_USER_PREFIX + userId);
        if (userObject == null) {
            // 登录信息丢失,重新登录获取
            return ResponseUtil.unLogin();
        }
        MobileUserInfo userInfo = JSONObject.toJavaObject(JSONObject.parseObject(userObject), MobileUserInfo.class);

        WxMaPhoneNumberInfo phoneNumberInfo = this.wxMaOperateService.getUserService().getPhoneNoInfo(userInfo.getSessionKey(), encryptedData, iv);
        String phone = phoneNumberInfo.getPhoneNumber();
        YipaoAdmin admin = adminService.findByMobile(phone);
        if (admin == null) {
            return ResponseUtil.fail(ResponseUtil.STATUS_CODE_BAD_ARGUMENT, "该手机号码不是管理员");
        }
        String adminMobile = admin.getMobile();
        if (StringUtils.isEmpty(adminMobile)) {
            return ResponseUtil.fail(ResponseUtil.STATUS_CODE_UN_AUTH, "请先在管理端绑定手机号码");
        }
        if (!phone.equals(adminMobile)) {
            return ResponseUtil.fail(ResponseUtil.STATUS_CODE_UN_AUTH, "不是运营人员");
        }
        // 判断用户对应的角色是否有管理端的权限
        if (!permissionService.checkOperatePermission(admin.getRoleIds())) {
            return ResponseUtil.fail(ResponseUtil.STATUS_CODE_UN_AUTH, "没有运营权限");
        }
        // 修改微信开放id
        admin.setWeixinOpenid(userInfo.getOpenId());
        if (adminService.updateById(admin) == 0) {
            return ResponseUtil.updatedDataFailed();
        }
        userInfo.setMobile(phone);
        userInfo.setUserId(admin.getId());
        // 前端重新赋值token,因为前面设置的用户id为虚拟id
        Map<Object, Object> result = new HashMap<Object, Object>(2);
        result.put("token", UserTokenManager.generateToken(admin.getId()));
        result.put("userInfo", userInfo);

        return ResponseUtil.ok(result);
    }
}
